#    Copyright 2012 New Mexico EPSCoR
#
#    This file is part of Teacher's P.E.T.
#
#    Teacher's P.E.T. is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Teacher's P.E.T. is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Teacher's P.E.T..  If not, see <http://www.gnu.org/licenses/>.
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".

Replace this with more appropriate tests for your application.
"""
import datetime
import os
from django.test import TestCase
from django.http import Http404
from django.core.files import File as DjangoFile
from django.contrib.auth.models import User

from apps.course.models import Course
from apps.activities.models import Activity, ActivityAutogradeResponse, ActivityAutogradeResponseForm, ActivityTemplate, ActivityTemplateForm, ActivityEditForm, ActivityQuestion, ActivityQuestionForm
from apps.activities.models import ActivityResponse, ActivityResponseBoolean, ActivityResponseBooleanTFForm, ActivityResponseBooleanYNForm, ActivityResponseFileUpload, ActivityResponseFileUploadForm
from apps.activities.models import ActivityResponseFloat, ActivityResponseFloatForm, ActivityResponseForm, ActivityResponseFormContainer, ActivityResponseFormsetContainer, ActivityResponseGradingForm
from apps.activities.models import ActivityResponseInteger, ActivityResponseIntegerForm, ActivityResponseLongAnswer, ActivityResponseLongAnswerForm, ActivityResponseMultipleChoice
from apps.activities.models import ActivityResponseMultipleChoiceBoxForm, ActivityResponseMultipleChoiceRadioForm, ActivityResponseShortAnswer, ActivityResponseShortAnswerForm
from apps.activities.models import ActivityUploadInput, ActivityViewed, Subactivity, SubactivityForm

#Instructors can
#   - edit activities
#   - add templates
#   - change templates
#   - add questions to an activity
#   - dynamically start/end activity questions when viewing an activity
#   - delete activities

#Assistants can do anything Instructors can do here

#Students can
#   - view activities
#   - submit answers to activity questions

#Activity limitations
#   - activities can not have themselves as a parent or child (at any level)

#Activity views
#   - view
#       - course must exist
#       - category and title must exist and lead to actual Activity
#       - if collection_category and collection_title are present, they must lead to actual Activity and it must have category/title activity as subactivity
#       - non-public activities can not be viewed by non-course-participants (public and users only in other courses)
#       - ActivityViewed must be updated unless there is valid POST data
#       - Once an activity is completed, the activityviewed should have completed attribute set
#   - view_question
#   - download

#Activity models
class ActivityModelsTestCase(TestCase):
    def setUp(self):
        self.user1 = User(first_name='test', last_name='user', username='testuser', email='test_user@no.com')
        self.user1.save()
        
        self.course1 = Course(course_id='test_course',course_title='Test Course')
        self.course1.save()
        
        self.activity_template1 = ActivityTemplate(category="Template Category 1",title="Template Title 1");
        self.activity_template1.save()
        self.activity_template2 = ActivityTemplate(category="Template Category 1",title="Template Title 2",description="Template Description 2");
        self.activity_template2.save()
        
        self.activity1 = Activity(title="Test Activity 1", category="Tests", course=self.course1.course_id)
        self.activity1.save()
        self.activity2 = Activity(title="Test Activity 2", category="Tests", course=self.course1.course_id)
        self.activity2.save()
        self.activity3 = Activity(title="Test Activity 3", category="Tests", course=self.course1.course_id)
        self.activity3.save()
        
        self.activity2_question1 = ActivityQuestion(content_object=self.activity2,type='BOOL-TF')
        self.activity2_question1.save()
        self.activity2_question2 = ActivityQuestion(content_object=self.activity2,type='BOOL-YN')
        self.activity2_question2.save()
        self.activity2_question3 = ActivityQuestion(content_object=self.activity2,type='CHAR')
        self.activity2_question3.save()
        self.activity2_question4 = ActivityQuestion(content_object=self.activity2,type='TEXT')
        self.activity2_question4.save()
        self.activity2_question5 = ActivityQuestion(content_object=self.activity2,type='INT')
        self.activity2_question5.save()
        self.activity2_question6 = ActivityQuestion(content_object=self.activity2,type='FLOAT')
        self.activity2_question6.save()
        self.activity2_question7 = ActivityQuestion(content_object=self.activity2,type='CHOICE-RADIO')
        self.activity2_question7.save()
        self.activity2_question8 = ActivityQuestion(content_object=self.activity2,type='CHOICE-BOX')
        self.activity2_question8.save()
        self.activity2_question9 = ActivityQuestion(content_object=self.activity2,type='UPLOAD')
        self.activity2_question9.save()
        
        self.activity2_question1_response1 = ActivityResponseBoolean(user=self.user1, section=self.activity2_question1,response=True)
        self.activity2_question1_response1.save()
        self.activity2_question2_response1 = ActivityResponseBoolean(user=self.user1, section=self.activity2_question2,response=False)
        self.activity2_question2_response1.save()
        self.activity2_question3_response1 = ActivityResponseShortAnswer(user=self.user1, section=self.activity2_question3,response='tiny little response here')
        self.activity2_question3_response1.save()
        self.activity2_question4_response1 = ActivityResponseLongAnswer(user=self.user1, section=self.activity2_question4,response='big long response here')
        self.activity2_question4_response1.save()
        self.activity2_question5_response1 = ActivityResponseInteger(user=self.user1, section=self.activity2_question5,response=42)
        self.activity2_question5_response1.save()
        self.activity2_question6_response1 = ActivityResponseFloat(user=self.user1, section=self.activity2_question6,response=3.1415926)
        self.activity2_question6_response1.save()
        self.activity2_question7_response1 = ActivityResponseMultipleChoice(user=self.user1, section=self.activity2_question7,response='0')
        self.activity2_question7_response1.save()
        self.activity2_question8_response1 = ActivityResponseMultipleChoice(user=self.user1, section=self.activity2_question8,response='1')
        self.activity2_question8_response1.save()
        self.activity2_question9_response1 = ActivityResponseFileUpload(user=self.user1, section=self.activity2_question9,response=DjangoFile(open('settings.py'),'test_file.pdf'))
        self.activity2_question9_response1.save()

#   - ActivityTemplate
#       - __unicode__, find, find_or_404
    def test_ActivityTemplate_unicode(self):
        #__unicode__
        self.assertEqual('%s' % self.activity_template1, '%s' % self.activity_template1.title)
        self.assertEqual('%s' % self.activity_template2, '%s - %s' % (self.activity_template2.title, self.activity_template2.description))
    def test_ActivityTemplate_find(self):
        #find(id=None,keep_queryset=False)
        #find should find both templates added in setup
        self.assertIn(self.activity_template1, ActivityTemplate.find())
        self.assertIn(self.activity_template2, ActivityTemplate.find())
        #testing keep_queryset and id
        self.assertEqual(self.activity_template1, ActivityTemplate.find(id=self.activity_template1.id))
        self.assertEqual(self.activity_template1, ActivityTemplate.find(id=self.activity_template1.id,keep_queryset=False))
        self.assertIn(self.activity_template1, ActivityTemplate.find(id=self.activity_template1.id,keep_queryset=True))
        self.assertNotEqual(self.activity_template2, ActivityTemplate.find(id=self.activity_template1.id))
    def test_ActivityTemplate_find_or_404(self):
        #same tests as find()
        self.assertIn(self.activity_template1, ActivityTemplate.find_or_404())
        self.assertIn(self.activity_template2, ActivityTemplate.find_or_404())
        #testing keep_queryset and id
        self.assertEqual(self.activity_template1, ActivityTemplate.find_or_404(id=self.activity_template1.id))
        self.assertEqual(self.activity_template1, ActivityTemplate.find_or_404(id=self.activity_template1.id,keep_queryset=False))
        self.assertIn(self.activity_template1, ActivityTemplate.find_or_404(id=self.activity_template1.id,keep_queryset=True))
        self.assertNotEqual(self.activity_template2, ActivityTemplate.find_or_404(id=self.activity_template1.id))
        #testing the 404
        self.assertRaises(Http404,ActivityTemplate.find_or_404,id=2000000)
#   - Subactivity
#       - save
    def test_Subactivity_save(self):
        subactivity = Subactivity(parent_activity=self.activity1,subactivity=self.activity2)
        self.assertTrue(subactivity.order_number is None)
        subactivity.save()
        self.assertTrue(subactivity.order_number is not None)
        self.assertEqual(subactivity.order_number,1)
#   - Activity
#       - __init__,__unicode__,has_uploads,has_started,has_ended,get_response,get_question,get_grades,
#           get_edit_url,get_parent_activities,get_link,get_subactivities,get_content_and_id,get_completed_info,
#           find,find_or_404,get_appearance_date,get_title,get_description
    def test_Activity_init(self):
        #init makes sure that no gradedsction is automatically created with an activity, so make sure one doesn't
        #   exist for one of the activities made in setUp
        self.assertEqual(len(self.activity1.sections.all()),0)
        self.assertEqual(len(self.activity2.sections.all()),9)
    def test_Activity_unicode(self):
        self.assertEqual('%s'%self.activity1,"%s - %s" % (self.activity1.category, self.activity1.title))
        self.assertEqual('%s'%self.activity2,"%s - %s" % (self.activity2.category, self.activity2.title))
    def test_Activity_has_uploads(self):
        self.assertFalse(self.activity1.has_uploads())
        self.assertTrue(self.activity2.has_uploads())
    def test_Activity_has_started(self):
        self.activity1.start_date = datetime.datetime.now()+datetime.timedelta(days=1)
        self.activity2.start_date = datetime.datetime.now()-datetime.timedelta(days=1)
        self.assertTrue(self.activity2.has_started())
        self.assertTrue(self.activity3.has_started())
        self.assertFalse(self.activity1.has_started())
    def test_Activity_has_ended(self):
        self.activity1.end_date=datetime.datetime.now()+datetime.timedelta(days=1)
        self.activity2.end_date = end_date=datetime.datetime.now()-datetime.timedelta(days=1)
        self.assertTrue(self.activity1.has_ended())
        self.assertFalse(self.activity3.has_ended())
        self.assertFalse(self.activity2.has_ended())
    def test_Activity_get_response(self):
        self.assertEqual(self.activity1.get_response(section=self.activity2_question1, user=self.user1),'__None')
        self.assertTrue('Download' in self.activity2.get_response(section=self.activity2_question9, user=self.user1))
        self.assertTrue('Response' in self.activity2.get_response(section=self.activity2_question4, user=self.user1))
        self.assertEqual(self.activity2.get_response(section=self.activity2_question1,user=self.user1),self.activity2_question1_response1.get_response(self.activity2_question1))
    def test_Activity_get_question(self):
        pass
        
#   - ActivityEditForm
#       - __init__, clean_subactivities
#   - ActivityViewed
#       - __unicode__, save
#   - ActivityQuestion
#       - __unicode__, save, get_choices, get_response, link, has_started, has_ended, get_response_forms
#   - ActivityResponse
#       - save, get_response
#   - ActivityResponseBoolean
#       - get_response
#   - ActivityResponseFileUpload
#       - activityUploadInput.render, get_submission_path, ActivityResponseFileUploadForm.clean_response
#   - ActivityResponseMultipleChoice
#       - __init__, get_response, ActivityResponseMultipleChoiceRadioForm.__init__, ActivityResponseMultipleChoiceBoxForm.__init__
#   - ActivityAutogradeResponse
#       - save
#   - ActivityResponseFormContainer
#       -__init__,__unicode__,title,points,question_number,original_question_number,question,
#           type,choices,allowable_extensions,start_date,end_date,link,submission_number,completed_date,response
#   - ActivityResponseFormsetContainer
#       - has_form
